// 装饰器的作用： 为某些属性，方法(方法参数)，类提供元数据信息(metadata);
// 元数据：描述数据的数据
// 装饰器的本质其实就是一个函数
// 装饰器是JS的内容，是需要参与运行的

// 由于装饰器还没有形成正是规范，所以在TS中需要打开配置experimentalDecorators:true

// 修饰类需要构造函数类型
// 1.简单的使用Function
// 2. new (...args: any[]) => any

// function classDecoration(target:new (...args:any[])=>any) { 
//   console.log("classDecoration");
//   console.log(target);
// }

// @classDecoration
// class A{

// }

// 使用泛型约束
/*
type Constructor<T = any> = new (...args: any[]) => T;

type User = {
  id: number;
  name: string;
  info(): void
}

function classDecoration<T extends Constructor<User>>(target:T) { 
  console.log("classDecoration");
  console.log(target);
}

@classDecoration
class A{
  constructor(public id: number, public name: string) { }
  info(){}
}
*/

// 装饰器工厂模式
type Constructor<T = any> = new (...args: any[]) => T;


/* function classDecorator<T extends Constructor>(str: string) {
  console.log("这里其实就是普通方法:" + str);
  return function (target: T) {
    console.log("classDecorator")
    console.log(target);
    console.log("这里是类装饰器:" + str)
    target.prototype.name = str;
  }
}

@classDecorator("hello TS")
class A{

}

let a = new A();
console.log((a as any).name) */

/*
function classDecorator<T extends Constructor>(target: T) {
  return class extends target{
    newProperty = "new Property"
    hello = "hello"
    name = "override name rose";
    info() { 
      console.log("this is info")
    }
    show() { 
      console.log("override show")
    }
  }
}

@classDecorator
class A{
  name = "jack";
  show() { 
    console.log("show")
  }
}

const objA = new A();
console.log(objA.name);
objA.show();
console.log((objA as any).newProperty);
(objA as any).info();
*/

// 多装饰器
// 普通函数安装顺序执行
// 装饰器按照从下到上的顺序执行

function classDecorator1<T extends Constructor>(str: string) { 
  console.log("classDecorator1函数的参数:" + str)
  return function (target: T) {
    console.log("classDecorator1类装饰器" + str);
  }
}

function classDecorator2<T extends Constructor>(str: string) { 
  console.log("classDecorator2函数的参数:" + str)
  return function (target: T) {
    console.log("classDecorator2类装饰器" + str);
  }
}

@classDecorator1("1")
@classDecorator2("2")
class A{
  
}
